#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

#include "../include/bondi.h"

//arma el request para la ciudad,  quien agrega el bus a la ciudad
void injectBondi(marshallADT mar, bondiT * bondi, busReqT * msg);

//se fija si el bus esta o no en una parada, y si esta dvuelve el indice de la parada
int parada(coords curPos, coords * stops, int cantstops);

static coords movMap[3][4]={{{-1,0},{1,0},{0,-1},{0,1}},
				{{0,-1},{0,1},{1,0},{-1,0}},
				{{1,0},{-1,0},{0,1},{0,-1}}};

//para el manejo de señales
static int exitFlag = 0;
static void
exitSigInt(int sign) {
	exitFlag = 1;
}

void
manageBondi(bondiT * bondi, coords * stops, int cantstops) {

	int mov, cantMov, aux, stopflag=0;
	marshallADT marCity, marLine;
	busReqT msg;
	coords cordChange;
	stopReqT stop;

	stop.nrobondi=bondi->bondi;

	/*con ciudad los bondis se usan de forma par, con su linea de forma impar*/
	if((marCity = getMarsh(bondi->linea * 200 + bondi->bondi*2 , CITY_ID)) == NULL)
		kill(0, SIGUSR1);

	/*con ciudad las lineas se usan de forma par, con sus colectivo de forma impar*/
	if((marLine = getMarsh(bondi->linea * 200 + (bondi->bondi*2)-1, (bondi->linea*2)-1+10)) == NULL)
		kill(0, SIGUSR1);

	//handler de la señal de mi padre para cerrarme bien
	static struct sigaction act;
	act.sa_handler = exitSigInt;
	sigfillset(&(act.sa_mask));
	sigaction(SIGUSR1, &act, NULL);

	mov = bondi->indice;
	cantMov = bondi->longTrayecto;

	msg.busN = bondi->bondi;
	msg.busLine = bondi->linea;
	msg.pasajeros=0;

	sleep(bondi->horaInicio);

	injectBondi(marCity, bondi, &msg);

	msg.type = BUS_MOVE;

	while(!exitFlag){
//		hacer el movimiento mov del bondi->trayecto

		msg.curPos.x = bondi->curPos.x;
		msg.curPos.y = bondi->curPos.y;
		msg.move = bondi->trayecto[mov];
		msg.orientation = bondi->sentidoActual;

		if(stopflag) {
			//tiempo que se tarda en una parada
			sleep(1);
			stopflag=0;
		}
		else
			usleep(1000000/bondi->vel);

		char ans = ' ';
		if((stop.parada=parada(msg.curPos, stops, cantstops)) != -1) {
			//si estoy en una parada, proceso pasajeros
			sendData(marLine, &stop, BUS_L);

			recvData(marLine, &ans, BUS_L);
			switch((int)ans) {
				case DONTSTOP: ans=' '; break;
				case PUP: ans='G'; stopflag=1; msg.pasajeros++; break;
				case PDOWN: ans='G'; stopflag=1; msg.pasajeros--; break;
				case PBOTH: ans='G'; stopflag=1; break; //sube y baja un pasajero
				default: break;
			}
		}

		while(ans!='G' && !exitFlag){
			sendData(marCity, &msg, BUS_C);

			recvData(marCity, &ans, BUS_C);

			if(ans == 'G'){
				//si la ciudad me permitio moverme, me muevo
				cordChange = movMap[(int)msg.move][(int)msg.orientation];
				bondi->curPos.x = bondi->curPos.x + cordChange.x;
				bondi->curPos.y = bondi->curPos.y + cordChange.y;

				if((aux = (int)msg.move) != CENTER){
					switch(bondi->sentidoActual){
					case NORTH: bondi->sentidoActual = (aux == RIGHT)? EAST:WEST;break;
					case SOUTH: bondi->sentidoActual = (aux == RIGHT)? WEST:EAST;break;
					case EAST: bondi->sentidoActual = (aux == RIGHT)? SOUTH:NORTH;break;
					case WEST: bondi->sentidoActual = (aux == RIGHT)? NORTH:SOUTH;break;
					default: break;
					}
				}

				mov++;
				if(mov == cantMov)
					mov = 0;
			}

		}
	}

	free(stops);
	closeMarsh(marCity);
	closeMarsh(marLine);

	exit(1);
}

int
parada(coords curPos, coords * stops, int cantstops) {
	int i, found=0;

	for(i=0; i<cantstops && !found; i++){
		if(stops[i].x==curPos.x && stops[i].y==curPos.y)
			found=1;
	}

	if(found)
		return i;
	return -1;
}

void
injectBondi(marshallADT mar, bondiT * bondi, busReqT * msg){

	char ans = ' ';

	msg->type = BUS_CREATE;
	msg->curPos.x = bondi->curPos.x;
	msg->curPos.y = bondi->curPos.y;
	msg->move = bondi->trayecto[0];
	msg->orientation = bondi->sentidoActual;

	while(ans!='O' && !exitFlag){
		sendData(mar, msg, BUS_C);
		recvData(mar, &ans, BUS_C);
	}
}
